﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Wx.Standard.Base;
using Wx.Standard.Common;
using Wx.Standard.Extend;
using Wx.Standard.IService;
using Wx.Standard.Model;
using Wx.Standard.Model.Receive;
using Wx.Standard.Model.Send;
using static Wx.Standard.Enum.Receive;

namespace Wx.Standard.Service
{
    public class GetMessage : IGetMessage
    {
        WxApi wxApi;
        /// <summary>
        /// 微信给过来的消息内容
        /// </summary>
        private string weChatMsg;
        /// <summary>
        /// 基础消息->可判断消息类型
        /// </summary>
        private ReceiveMsg receiveMsg;
        /// <summary>
        /// url参数
        /// </summary>
        private Dictionary<string, string> urlParams;
        internal GetMessage(WxApi wxApi)
        {
            this.wxApi = wxApi;
            var urlvalue = wxApi.context.Request.QueryString.Value;
            urlParams = ModelHelper.urlParameterToDictionary(urlvalue);
            ReceiveMessages();
        }
        private GetMessage() { }
        #region 实现

        string IGetMessage.AllMsg(Func<ReceiveMsg,string> actionMsg)
        {
            return actionMsg(receiveMsg);
        }
        string IGetMessage.ClickMenuMsg(Func<ReceiveEventWithClickMenu, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.CLICK.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithClickMenu>(weChatMsg);
                        return actionMsg(model);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.ImageMsg(Func<ReceiveMsgWithImage, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.image.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithImage>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.LocationMsg(Func<ReceiveMsgWithLocation, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.location.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithLocation>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.ScanningQRcodeMsg(Func<ReceiveEventWithQRcode, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.SCAN.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithQRcode>(weChatMsg);
                        if (!string.IsNullOrWhiteSpace(model.EventKey))
                        {
                            return actionMsg(model);
                        }
                    }
                    if (baseevent.Event == Event.subscribe.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithQRcode>(weChatMsg);
                        if (model.EventKey.Contains("qrscene_"))
                        {
                            model.EventKey = model.EventKey.Replace("qrscene_", "");
                            return actionMsg(model);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.SubscribeMsg(Func<ReceiveEventBase, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.subscribe.ToString())
                    {
                        return actionMsg(baseevent);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.TextMsg(Func<ReceiveMsgWithText, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.text.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithText>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.UnSubscribeMsg(Func<ReceiveEventBase, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.unsubscribe.ToString())
                    {
                        return actionMsg(baseevent);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.UploadLocationMsg(Func<ReceiveEventWithLocation, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.LOCATION.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithLocation>(weChatMsg);
                        return actionMsg(model);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.UrlMsg(Func<ReceiveMsgWithUrl, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.link.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithUrl>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.VideoMsg(Func<ReceiveMsgWithVideo, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.video.ToString() || receiveMsg.MsgType == MsgType.shortvideo.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithVideo>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }

        string IGetMessage.ViewMenuMsg(Func<ReceiveEventWithClickMenu, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.VIEW.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithClickMenu>(weChatMsg);
                        return actionMsg(model);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }
        string IGetMessage.ModelMsgNotify(Func<ReceiveEventWithModelMsg, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.@event.ToString())
                {
                    var baseevent = XmlHelper.deserialize<ReceiveEventBase>(weChatMsg);
                    if (baseevent.Event == Event.TEMPLATESENDJOBFINISH.ToString())
                    {
                        var model = XmlHelper.deserialize<ReceiveEventWithModelMsg>(weChatMsg);
                        return actionMsg(model);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }
        string IGetMessage.VoiceMsg(Func<ReceiveMsgWithVoice, string> actionMsg)
        {
            try
            {
                if (receiveMsg.MsgType == MsgType.voice.ToString())
                {
                    var model = XmlHelper.deserialize<ReceiveMsgWithVoice>(weChatMsg);
                    return actionMsg(model);
                }
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
            return "";
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 验证微信服务器的数据
        /// </summary>
        private bool CheckSign
        {
            get
            {
                if (urlParams == null)
                {
                    return false;
                }
                var signature = urlParams["signature"];
                var timestamp = urlParams["timestamp"]; ;
                var nonce = urlParams["nonce"];
                string[] array = { wxApi.apiOption.token, timestamp, nonce };
                Array.Sort(array);
                var arrayString = string.Join("", array);
                var str = StringEncyptionHelper.sha1(arrayString).ToLower();
                if (string.Compare(str, signature.ToLower(), true) == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        /// <summary>
        /// 接收微信服务器消息
        /// </summary>
        private void ReceiveMessages()
        {
            if (this.CheckSign)
            {
                if (wxApi.context.Request.Method.ToUpper() == "POST")
                {
                    using (Stream stream = wxApi.context.Request.Body)
                    {
                        byte[] bytes = new byte[wxApi.context.Request.ContentLength.Value];
                        stream.Read(bytes, 0, bytes.Length);
                        stream.Dispose();

                        string postString = Encoding.UTF8.GetString(bytes);
                        if (!string.IsNullOrEmpty(postString))
                        {
                            weChatMsg = postString;
                            receiveMsg = XmlHelper.deserialize<ReceiveMsg>(weChatMsg);
                            wxApi.openId = receiveMsg.FromUserName;
                            wxApi.ownId = receiveMsg.ToUserName;
                        }
                    }
                }
                else
                {
                    Encoding.GetEncoding("utf-8");
                    string echoString = urlParams["echostr"];
                    wxApi.context.Response.WriteAsync(echoString);

                }
            }
            else
            {
                throw new WeChatError("验签不通过");
            }
        }


        #endregion

        #region 被动回复消息
        string IGetMessage.ReplyNewsMsg(IList<ResponseItem> list)
        {
            if (list.Count > 10)
            {
                throw new WeChatError("图文消息不能超过10条");
            }
            ResponsNewsMsg news = new ResponsNewsMsg()
            {
                FromUserName = wxApi.ownId,
                ToUserName = wxApi.openId,
                MsgType = "news",
                CreateTime = (uint)StringHelper.convertDateTimeInt(DateTime.Now),
                ArticleCount = list.Count,
                Articles = list
            };
            var str = XmlHelper.serialize(news);
            return str;
        }

        string IGetMessage.ReplyTextMsg(string content)
        {
            ResponseTextMsg testMsg = new ResponseTextMsg()
            {
                FromUserName = wxApi.ownId,
                ToUserName = wxApi.openId,
                MsgType = "text",
                CreateTime = (uint)StringHelper.convertDateTimeInt(DateTime.Now),
                Content = content
            };
            var str = XmlHelper.serialize(testMsg);
            return str;
        }
        #endregion

        WeChatUser IGetMessage.GetUser()
        {
            try
            {
                var access_token = BaseClass.getAccessToken(wxApi.apiOption);
                var url = $"https://api.weixin.qq.com/cgi-bin/user/info?access_token={access_token}&openid={wxApi.openId}&lang=zh_CN";
                var str = BaseClass.getFormWechatService(url);
                var user = JsonHelper.jsonToModel<WeChatUser>(str);
                return user;
            }
            catch (Exception ex)
            {
                throw new WeChatError($"{this.GetType().Name}:{ex.Message}");
            }
        }
    }
}
